function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

const path = require("path");
const NAME = /^[a-zA-Z0-9\u4e00-\u9fa5\:\-_]+$/;
function isName(name) {
	if (typeof name !== "string") {
		return false;
	}
	return NAME.test(name);
}
//默认创建者
const Xcreator = {
	base({ task, async: parallel, strict }) {
		var _this = this;

		return _asyncToGenerator(function* () {
			if (!(task instanceof Array)) {
				return null;
			}
			task = yield Promise.all(task.map(function (t) {
				return _this.task(t);
			}));
			if (strict) {
				task.map(function (x) {
					if (!x) {
						task = null;
					}
				});
			} else {
				task = task.filter(function (x) {
					return x;
				});
			}
			if (!task) {
				return null;
			}
			if (parallel) {
				return function (arg) {
					return Promise.all(task.map(x => x(arg, this)));
				};
			}
			return (() => {
				var _ref = _asyncToGenerator(function* (arg) {
					for (let i = 0, l = task.length; i < l; i++) {
						arg = yield task[i](arg, this);
					}
					return arg;
				});

				return function (_x) {
					return _ref.apply(this, arguments);
				};
			})();
		})();
	}
};

//创建者代理配置
const creatorProxy = {
	apply(creator, object, args) {
		return creator.create(...args);
	},
	construct(creator, args) {
		return creator.new(...args);
	}
};
//任务代理配置
const taskProxy = {
	apply(task, object, args) {
		return task.exec(...args);
	},
	construct(task, args) {
		return task.new(...args);
	}
};
//监视者代理配置
const watcherProxy = {
	apply(watcher, object, args) {
		return watcher.watch(...args);
	},
	construct(watcher, args) {
		return watcher.new(...args);
	}
};
//监视状态代理配置
const watchStateProxy = {
	apply(watchState, object, args) {
		return watchState.stop(...args);
	},
	construct(watchState, args) {
		return watchState.new(...args);
	}
};
/**
 * 信息输出(默认)
 * @param  {String} options.lv 等级
 * @param  {String} options.tp 类型
 * @param  {String} options.at 所在模块
 * @param  {String} options.fn 文件名
 * @param  {Number} options.ln 行号
 * @param  {Number} options.cl 列号
 * @param  {String} options.tx 错误信息
 */
function print({ lv, tp, at, fn, ln, cl, tx }) {
	if (tp) {
		tp = ":" + tp;
	}
	if (at) {
		at = "@" + at;
	}
	if (path.isAbsolute(fn)) {
		fn = path.relative(this.XBWP, fn);
	}
	tx.replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\f/g, "\\f");
	console.log(`${lv}${tp}${at}\t[${fn}:${ln}:${cl}]\t${tx}`);
}
/**
 * Xauto代理
 */
let XautoProxy = {
	apply(Xauto, object, [{
		opt, pkg, echo, XBWP, XPBP,
		plugin = [],
		creator = {},
		task = {},
		watcher = {},
		exec = [],
		watch = {},
		script
	} = {}]) {
		return _asyncToGenerator(function* () {
			const xauto = new Xauto({ opt, pkg, echo, XBWP, XPBP });

			if (!(plugin instanceof Array)) {
				plugin = [];
			}
			if (typeof creator !== "object" || !creator) {
				creator = {};
			}
			if (typeof task !== "object" || !task) {
				task = {};
			}
			if (typeof watcher !== "object" || !watcher) {
				watcher = {};
			}
			if (!(exec instanceof Array)) {
				exec = [];
			}
			if (typeof watch !== "object" || !watch) {
				watch = {};
			}
			if (typeof script !== "string" || !script) {
				script = '';
			}

			for (let k in Xcreator) {
				yield xauto.creator(Xcreator[k], `Xauto:${k}`);
			}

			for (let i = 0, l = plugin.length; i < l; i++) {
				yield xauto.plugin(plugin[i]);
			}

			for (let k in creator) {
				yield xauto.creator(creator[k], k);
			}
			for (let k in task) {
				yield xauto.task(task[k], k);
			}
			for (let k in watcher) {
				yield xauto.watcher(watcher[k], k);
			}
			exec.map(function (e) {
				return xauto.exec(e);
			});
			for (let k in watch) {
				let ws = watch[k];
				if (!(ws instanceof Array)) {
					continue;
				}
				xauto.register((yield xauto.watch(...ws)), k);
			}
			if (script) {
				script = path.resolve(xauto.XBWP, script);
				try {
					script = require(script);
				} catch (e) {}
				if (typeof script === "function") {
					try {
						script(Xauto);
					} catch (e) {}
				}
			}
			return xauto;
		})();
	}
};
/**
 * 上下文this
 */
let Context = (_ => {
	let contextProxy = {
		apply(context, object, args) {
			context.echo(...args);
		},
		setPrototypeOf() {
			return false;
		},
		getPrototypeOf() {
			return Context.prototype;
		}
	};
	let proxy = {
		apply(Context, object, [c, x]) {
			if (c instanceof Context) {
				return c;
			}
			return proxy.construct(Context, [x]);
		},
		construct(Context, [xauto]) {
			let context = new Context();
			Object.setPrototypeOf(context, xauto);
			Object.defineProperties(context, { $: { value: {}, enumerable: true } });
			return new Proxy(context, contextProxy);
		}
	};
	return new Proxy(class Context extends Function {}, proxy);
})();
/**
 * 任务
 */
class Task extends Function {
	constructor(task, opt, ...args) {
		super();
		if (typeof opt != "object") opt = {};
		if (task instanceof Task) {
			this._task = task._task;
			this.Xauto = task.Xauto;
			this._opt = Object.assign({}, task._opt, opt);
			let _args = this._args = Object.create(task._args);
			args.map(x => _args.push(x));
		} else if (task instanceof Array && isFunction(task[0]) && task[1] instanceof Xauto) {
			this._task = task[0];
			this.Xauto = task[1];
			this._opt = Object.assign({}, opt);
			let _args = this._args = [];
			args.map(x => _args.push(x));
		} else {
			throw new Error("非法的task");
		}
	}
	/**
  * 执行此任务
  * @param  {any} arg     任务的参数
  * @param  {Context} context 上下文this
  * @return {any}         任务返回值
  */
	exec(arg, context) {
		var _this2 = this;

		return _asyncToGenerator(function* () {
			return yield _this2._task.call(Context(context, _this2.Xauto), arg, _this2._opt, ..._this2._args);
		})();
	}
	/**
  * 基于当前任务创建
  * @param  {any}    opt  选项
  * @param  {...any} args 参数
  * @return {Task}        创建的任务
  */
	new(...args) {
		return new Proxy(new Task(this, ...args), taskProxy);
	}
}

class WatchState extends Function {
	constructor() {
		super();
		this._watching = true;
	}
	get watching() {
		return this._watching;
	}
	get watch() {
		return this._watcher;
	}
	emit(arg) {
		if (!this._watching) {
			return;
		}
		this._task(arg).catch(handle.bind(this.Xauto));
	}
	stop() {
		var _this3 = this;

		return _asyncToGenerator(function* () {
			if (!_this3._watching) {
				return;
			}
			_this3._watching = false;
			try {
				_this3._handle.call(null);
			} catch (e) {}
		})();
	}
	new(...args) {
		return this._watcher.new(...args);
	}
}
/**
 * 监视者
 */
class Watcher extends Function {
	constructor(watcher, opt, ...args) {
		super();
		if (typeof opt !== "object") {
			opt = {};
		};
		if (watcher instanceof Watcher) {
			this._watcher = watcher._watcher;
			this.Xauto = watcher.Xauto;
			this._opt = Object.assign({}, watcher._opt, opt);
			let _args = this._args = Object.create(watcher._args);
			args.map(x => _args.push(x));
		} else if (watcher instanceof Array && isFunction(watcher[0]) && watcher[1] instanceof Xauto) {
			this._watcher = watcher[0];
			this.Xauto = watcher[1];
			this._opt = Object.assign({}, opt);
			let _args = this._args = [];
			args.map(x => _args.push(x));
		} else {
			throw new Error("非法的watcher");
		}
	}
	/**
  * 开始监听
  * @param  {Task}		task	事件发生后执行的任务
  * @return {WatchState}			产生的事件监听
  */
	watch(task) {
		var _this4 = this;

		return _asyncToGenerator(function* () {
			task = yield _this4.Xauto.task(task);
			if (!task) {
				return null;
			}
			if (task.Xauto !== _this4.Xauto) {
				throw new Error("监视者与任务属于同一个Xauto");
			}
			let ws = new WatchState();
			ws.Xauto = _this4.Xauto;
			ws._watcher = _this4;
			ws._task = task;
			try {
				ws._handle = yield _this4._watcher.call(new Context(_this4.Xauto), ws.emit.bind(ws), _this4._opt, ..._this4._args);
				return new Proxy(ws, watchStateProxy);
			} catch (e) {
				handle.call(_this4.Xauto, e);
			}
		})();
	}
	/**
  * 基于当前监视者创建
  * @param  {any}		opt		选项
  * @param  {...any}		args	参数
  * @return {Watcher}			创建的监视者
  */
	new(opt, ...args) {
		return new Proxy(new Watcher(this, opt, ...args), watcherProxy);
	}
}

class Creator extends Function {
	constructor(creator, opt, ...args) {
		super();
		if (typeof opt !== "object") {
			opt = {};
		};
		if (creator instanceof Creator) {
			this._creator = creator._creator;
			this.Xauto = creator.Xauto;
			this._opt = Object.assign({}, creator._opt, opt);
			let _args = this._args = Object.create(creator._args);
			args.map(x => _args.push(x));
		} else if (creator instanceof Array && isFunction(creator[0]) && creator[1] instanceof Xauto) {
			this._creator = creator[0];
			this.Xauto = creator[1];
			this._opt = Object.assign({}, opt);
			let _args = this._args = [];
			args.map(x => _args.push(x));
		} else {
			throw new Error("非法的creator");
		}
	}
	/**
  * 创建任务
  * @param  {Object}		cfg		创建任务的参数
  * @return {Task}				创建的任务
  */
	create(cfg) {
		var _this5 = this;

		return _asyncToGenerator(function* () {
			let task = yield _this5._creator.call(Context(null, _this5.Xauto), cfg, _this5._opt, ..._this5._args);
			if (typeof task === "function") {
				task = new Proxy(new Task([task, _this5.Xauto]), taskProxy);
			} else if (!(task instanceof Task)) {
				task = null;
			}
			return task;
		})();
	}
	/**
  * 基于当前创建者创建
  * @param  {any}    opt		选项
  * @param  {...any} args	参数
  * @return {Creator}		创建的创建者
  */
	new(opt, ...args) {
		return new Proxy(new Creator(this, opt, ...args), creatorProxy);
	}
}

class XautoError extends Error {}

class Xauto {
	/**
  * 构造Xauto
  * @param	{Object}	options.opt		插件配置
  * @param	{Object}	options.pkg		程序包配置
  * @param	{Function}	options.echo	信息输出函数
  * @param	{String}	options.XBWP	Xauto基本工作路径
  * @param	{String}	options.XPBP	Xauto插件基本路径
  */
	constructor({
		opt = {},
		pkg = {},
		echo = print,
		XBWP = process.cwd(),
		XPBP = ""
	}) {
		if (!opt || typeof opt !== "object") {
			opt = {};
		}
		if (!pkg || typeof pkg !== "object") {
			pkg = {};
		}
		if (typeof echo !== "function") {
			echo = print;
		}
		if (typeof XBWP !== "string") {
			XBWP = "";
		}
		if (typeof XPBP !== "string") {
			XPBP = "";
		}
		if (!path.isAbsolute(XBWP)) {
			XBWP = path.resolve(process.cwd(), XBWP);
		}
		if (!path.isAbsolute(XPBP)) {
			XBWP = path.resolve(XBWP, XPBP);
		}
		Object.defineProperties(this, {
			_task: { value: {}, enumerable: true },
			_creator: { value: {}, enumerable: true },
			_watcher: { value: {}, enumerable: true },
			_watchState: { value: {}, enumerable: true },
			_plugin: { value: new Set(), enumerable: true },

			_print: { value: echo, enumerable: true },

			opt: { value: Object.freeze(opt), enumerable: true },
			pkg: { value: Object.freeze(pkg), enumerable: true },
			XBWP: { value: XBWP, enumerable: true },
			XPBP: { value: XPBP, enumerable: true },

			util: { value: {}, enumerable: true },

			creator: { value: this.creator, enumerable: true },
			task: { value: this.task, enumerable: true },
			watcher: { value: this.watcher, enumerable: true },
			watchState: { value: this.watchState, enumerable: true },
			register: { value: this.register, enumerable: true },
			plugin: { value: this.plugin, enumerable: true },
			exec: { value: this.exec, enumerable: true },
			throw: { value: this.throw, enumerable: true },
			echo: { value: this.echo, enumerable: true }
		});
	}
	/**
  * 创建或获取任务
  * @param	{any}		task	用于创建或获取任务的配置
  * @param	{String}	name	注册名
  * @return	{Task}				任务
  */
	task(task, name) {
		var _this6 = this;

		return _asyncToGenerator(function* () {
			let tasks = _this6._task;
			if (typeof task === "string") {
				//获取任务
				if (task in tasks) {
					task = tasks[task];
				} else {
					task = null;
				}
			} else if (task instanceof Task) {
				task = task;
			} else if (task instanceof Array) {
				let [t, opt, ...args] = task;
				task = t;
				if (typeof task === "string") {
					if (task in tasks) {
						task = tasks[task];
					} else {
						task = null;
					}
				} else if (isFunction(task)) {
					task = [task, _this6];
				} else if (!(task instanceof Task)) {
					task = null;
				}
				if (task) {
					task = new Proxy(new Task(task, opt, ...args), taskProxy);
				}
			} else if (isFunction(task)) {
				task = [task, _this6];
				task = new Proxy(new Task(task), taskProxy);
			} else if (typeof task === "object") {
				let creator = yield _this6.creator(task['']);
				if (!creator) {
					task = null;
				}
				if (task) {
					task = yield creator(task);
				}
			} else {
				task = null;
			}
			if (task && isName(name) && !(name in tasks)) {
				tasks[name] = task;
			}
			return task;
		})();
	}
	/**
  * 创建或获取监视者
  * @param	{any}		watcher	用于创建或获取监视者的配置
  * @param	{String}	name	注册名
  * @return	{Watcher}			监视者
  */
	watcher(watcher, name) {
		var _this7 = this;

		return _asyncToGenerator(function* () {
			const List = _this7._watcher;
			if (typeof watcher === "string") {
				if (watcher in List) {
					watcher = List[watcher];
				} else {
					watcher = null;
				}
			} else if (watcher instanceof Watcher) {
				watcher = watcher;
			} else if (isFunction(watcher)) {
				watcher = [watcher, _this7];
				watcher = new Proxy(new Watcher(watcher), watcherProxy);
			} else if (watcher instanceof Array) {
				let [w, opt, ...args] = watcher;
				watcher = w;
				if (typeof watcher === "string") {
					if (watcher in List) {
						watcher = List[watcher];
					} else {
						watcher = null;
					}
				} else if (isFunction(watcher)) {
					watcher = [watcher, _this7];
				} else if (!(watcher instanceof Task || isFunction(watcher))) {
					watcher = null;
				}
				if (watcher) {
					watcher = new Proxy(new Watcher(watcher, opt, ...args), watcherProxy);
				}
			} else {
				watcher = null;
			}
			if (watcher && isName(name) && !(name in List)) {
				List[name] = watcher;
			}
			return watcher;
		})();
	}

	/**
  * 获取监视状态
  * @param	{String}	name	监视状态名
  * @return	{Watcher}			监视状态
  */
	watchState(watchState) {
		var _this8 = this;

		return _asyncToGenerator(function* () {
			const List = _this8._watchState;
			if (typeof watchState === "string") {
				if (watchState in List) {
					watchState = List[watchState];
				} else {
					watchState = null;
				}
			} else {
				watchState = null;
			}
			return watchState;
		})();
	}
	/**
  * 创建或获取创建者
  * @param	{any}		watcher	用于创建或获取创建者的配置
  * @param	{String}	name	注册名
  * @return	{Creator}			创建的创建者
  */
	creator(creator, name) {
		var _this9 = this;

		return _asyncToGenerator(function* () {
			const List = _this9._creator;
			if (typeof creator === "string") {
				if (creator in List) {
					creator = List[creator];
				} else {
					creator = null;
				}
			} else if (creator instanceof Creator) {
				creator = creator;
			} else if (isFunction(creator)) {
				creator = new Proxy(new Creator([creator, _this9]), creatorProxy);
			} else if (creator instanceof Array) {
				let [c, opt, ...args] = creator;
				creator = c;
				if (typeof creator === "string") {
					if (creator in List) {
						creator = List[creator];
					} else {
						creator = null;
					}
				} else if (isFunction(creator)) {
					creator = [creator, _this9];
				} else if (!(creator instanceof Task)) {
					creator = null;
				}
				if (creator) {
					creator = new Proxy(new Creator(creator, opt, ...args), creatorProxy);
				}
			} else {
				creator = null;
			}
			if (creator && isName(name) && !(name in List)) {
				List[name] = creator;
			}
			return creator;
		})();
	}
	/**
  * 注册任务/监视者/监视状态
  * @param	{Object}	obj		要注册的任务/监视者/监视状态
  * @param	{String}	name	注册名
  * @return	{Boolean}			是否注册成功
  */
	register(obj, name) {
		var _this10 = this;

		return _asyncToGenerator(function* () {
			let list = null;
			if (obj instanceof Task) {
				list = _this10._task;
			} else if (obj instanceof Watcher) {
				list = _this10._watcher;
			} else if (obj instanceof WatchState) {
				list = _this10._watchState;
			} else if (obj instanceof Creator) {
				list = _this10._creator;
			} else {
				return false;
			}
			if (obj.Xauto !== _this10) {
				return false;
			}
			if (!isName(name)) {
				return false;
			}
			if (name in list) {
				return false;
			}
			list[name] = obj;
			return true;
		})();
	}
	/**
  * 装载插件(插件只会装载一次)
  * @param	{String}	name	插件名
  * @return	{Boolean}			是否已经载入且载入成功
  */
	plugin(name) {
		var _this11 = this;

		return _asyncToGenerator(function* () {
			let List = _this11._plugin;
			if (typeof name !== "string") {
				return false;
			}
			if (!name) {
				return false;
			}
			if (name === "Xauto") {
				return true;
			}
			if (List.has(name)) {
				return true;
			}
			let plugin = "xauto-plugin-" + name;
			try {
				plugin = require(plugin);
			} catch (e) {
				let p = _this11.XPBP;
				for (;;) {
					try {
						plugin = require(p + "/node_modules/" + plugin);
						break;
					} catch (e) {}
					try {
						plugin = require(p + "/" + plugin);
						break;
					} catch (e) {}
					let np = path.dirname(p);
					if (np === p) {
						return false;
					}
					p = np;
				}
			}
			if (typeof plugin === "function") {
				try {
					let plugin = yield plugin(_this11);
				} catch (e) {
					return false;
				}
			}
			if (typeof plugin !== "object" || !plugin) {
				return false;
			}
			let task = plugin.task;
			let creator = plugin.creator;
			let watcher = plugin.watcher;
			if (task) {
				for (let k in task) {
					yield _this11.task(task[k], `${name}:${k}`);
				}
			}
			if (creator) {
				for (let k in creator) {
					yield _this11.creator(creator[k], `${name}:${k}`);
				}
			}
			if (watcher) {
				for (let k in watcher) {
					yield _this11.watcher(watcher[k], `${name}:${k}`);
				}
			}
			List.add(name);
			return true;
		})();
	}
	/**
  * 执行一个任务
  * @param	{Task}		task	要执行的任务
  * @return	{Object}			任务结束返回的值
  */
	exec(task, cfg, context) {
		var _this12 = this;

		return _asyncToGenerator(function* () {
			task = _this12.task(task);
			if (!task) {
				return false;
			}
			try {
				yield task(cfg, context);
			} catch (e) {
				handle.call(_this12, e);
			}
			return true;
		})();
	}
	/**
  * 开始监视
  * @param	{Watcher}		watcher	监视者
  * @param	{Task}			task	任务
  * @return	{WatchState}			监视状态
  */
	watch(watcher, task) {
		var _this13 = this;

		return _asyncToGenerator(function* () {
			watcher = yield _this13.watcher(watcher);
			if (!watcher) {
				return null;
			}
			task = yield _this13.task(task);
			if (!task) {
				return null;
			}
			return yield watcher(task);
		})();
	}
	/**
  * 输出信息
  * @param  {String} options.lv 等级
  * @param  {String} options.tp 类型
  * @param  {String} options.at 所在模块
  * @param  {String} options.fn 文件名
  * @param  {Number} options.ln 行号
  * @param  {Number} options.cl 列号
  * @param  {String} options.tx 错误信息
  */
	echo({ lv = "info", tp, at, fn, ln, cl, tx } = {}) {
		if (typeof lv === "string") {
			lv = lv.replace(/[^a-zA-Z0-9 \-_]+/g, "").replace(/ /g, "-");
		} else {
			lv = "";
		}
		if (typeof tp === "string") {
			tp = tp.replace(/[^a-zA-Z0-9 \-_]+/g, "").replace(/ /g, "-");
		} else {
			tp = "";
		}
		if (typeof at === "string") {
			at = at.replace(/[^a-zA-Z0-9 \-_\:]+/g, "").replace(/ /g, "-");
		} else {
			at = "";
		}
		if (typeof fn === "string") {
			fn = fn.replace(/[\r\n\t\f\:"'`]+/g, "");
		} else {
			fn = "";
		}
		if (typeof ln !== "number") {
			ln = "";
		}
		if (typeof cl !== "number") {
			cl = "";
		}
		if (typeof tx !== "string") {
			tx = "";
		}
		this._print.call(this, { lv, tp, at, fn, ln, cl, tx });
	}
	/**
  * 抛出错误信息并结束当前任务
  */
	throw(output) {
		this.echo(output);
		throw new XautoError();
	}
}

/**
 * 是否为函数
 * @param	{Object}	func	被判断的对象
 * @return	{Boolean}			是否为函数
 */
function isFunction(func) {
	if (func instanceof Xauto) {
		return false;
	} else if (func instanceof Context) {
		return false;
	} else if (func instanceof Task) {
		return false;
	} else if (func instanceof Creator) {
		return false;
	} else if (func instanceof Watcher) {
		return false;
	} else if (func instanceof WatchState) {
		return false;
	} else if (typeof func === "function") {
		return true;
	} else {
		return false;
	}
}

/**
 * 错误处理器
 * @param  {Object} e 意外的错误
 */
function handle(e) {
	if (e instanceof XautoError) {
		return;
	} else if (e instanceof Error) {
		this.echo({ tx: e.stack });
	} else {
		this.echo(e);
	}
}

module.exports = new Proxy(Xauto, XautoProxy);